"""
音频处理工具类，提供音频处理相关功能
"""
import os
import logging
import tempfile
import numpy as np
from scipy.io import wavfile
from scipy import signal

from app.utils.logger import Logger

class AudioProcessor:
    """
    音频处理工具类
    """
    
    def __init__(self):
        """
        初始化音频处理工具类
        """
        self.logger = Logger.get_logger("audio_processor")
    
    @staticmethod
    def trim_silence(input_file, threshold=0.02, save_to_new_file=False):
        """
        去除音频文件开头和结尾的空白部分
        
        @param input_file: 输入音频文件路径
        @param threshold: 音量阈值，低于此值被视为静音，取值范围0-1
        @param save_to_new_file: 是否保存为新文件
        @return: 处理后的文件路径（如果save_to_new_file为True），否则返回原文件路径
        """
        logger = Logger.get_logger("audio_processor")
        
        try:
            # 检查文件是否存在
            if not os.path.exists(input_file):
                logger.error(f"文件不存在: {input_file}")
                return input_file
            
            # 读取音频文件
            sample_rate, audio_data = wavfile.read(input_file)
            
            # 如果是立体声，转换为单声道以简化处理
            if len(audio_data.shape) > 1:
                audio_data = audio_data.mean(axis=1)
            
            # 将音频数据类型转换为浮点型
            if audio_data.dtype != np.float32 and audio_data.dtype != np.float64:
                audio_data = audio_data.astype(np.float32)
                # 按照数据类型归一化数据
                if audio_data.dtype == np.int16:
                    audio_data = audio_data / 32768.0
                elif audio_data.dtype == np.int32:
                    audio_data = audio_data / 2147483648.0
                else:
                    audio_data = audio_data / np.max(np.abs(audio_data))
            
            # 计算音频包络线
            envelope = np.abs(audio_data)
            
            # 使用移动平均平滑包络
            window_size = int(sample_rate * 0.01)  # 10ms窗口
            if window_size > 1:
                envelope = np.convolve(envelope, np.ones(window_size)/window_size, mode='same')
            
            # 查找开始和结束的非静音点
            non_silence = envelope > threshold
            
            if not np.any(non_silence):
                logger.warning(f"文件全是静音，返回原文件: {input_file}")
                return input_file
            
            # 找到第一个非静音点
            start_idx = np.where(non_silence)[0][0]
            
            # 找到最后一个非静音点
            end_idx = np.where(non_silence)[0][-1]
            
            # 确保修剪后留有一点余量
            margin = int(sample_rate * 0.1)  # 100ms余量
            start_idx = max(0, start_idx - margin)
            end_idx = min(len(audio_data) - 1, end_idx + margin)
            
            # 获取修剪后的音频数据
            trimmed_audio = audio_data[start_idx:end_idx+1]
            
            # 判断修剪是否有效
            if len(trimmed_audio) < 0.5 * len(audio_data):
                # 如果修剪掉了超过50%的音频，才认为有效
                logger.info(f"音频静音修剪有效: {input_file} (修剪了 {100 * (1 - len(trimmed_audio) / len(audio_data)):.1f}%)")
                
                if save_to_new_file:
                    # 创建新文件名
                    base_name, ext = os.path.splitext(input_file)
                    output_file = f"{base_name}_trimmed{ext}"
                    
                    # 保存修剪后的音频
                    wavfile.write(output_file, sample_rate, trimmed_audio)
                    logger.info(f"保存修剪后音频到: {output_file}")
                    return output_file
                else:
                    # 覆盖原文件
                    wavfile.write(input_file, sample_rate, trimmed_audio)
                    logger.info(f"已覆盖原音频文件: {input_file}")
                    return input_file
            else:
                logger.info(f"音频无需修剪或修剪效果不明显: {input_file}")
                return input_file
                
        except Exception as e:
            logger.error(f"音频处理出错: {str(e)}")
            return input_file 